import { IPSAppDEField, IPSAppDEView, IPSAppView, IPSDEMultiEditViewPanel } from '@ibiz/dynamic-model-api';
import { ModelTool, Util, ViewTool } from '../../../util';
import { AppMDCtrlController } from './app-md-ctrl-controller';
import {
  IMobMEditViewPanelCtrlController,
  MobMEditViewPanelEvents,
  IParam,
  ICtrlActionResult,
  IViewStateParam,
  IUIDataParam,
} from '../../../interface';
import { AppMobMEditViewPanelService } from '../../ctrl-service';
export class MobMEditViewPanelCtrlController extends AppMDCtrlController implements IMobMEditViewPanelCtrlController {
  /**
   * @description 多表单编辑视图面板部件模型实例
   * @type {IPSDEMultiEditViewPanel}
   * @memberof MobMEditViewPanelCtrlController
   */
  public controlInstance!: IPSDEMultiEditViewPanel;

  /**
   * @description 多编辑表单面板样式
   * @type {string}
   * @memberof MobMEditViewPanelCtrlController
   */
  public panelStyle!: string;

  /**
   * @description 数据集合
   * @type {any[]}
   * @memberof MobMEditViewPanelCtrlController
   */
  public items: any[] = [];

  /**
   * @description 计数器
   * @private
   * @type {number}
   * @memberof MobMEditViewPanelCtrlController
   */
  private count: number = 0;

  /**
   * @description 关系实体参数对象
   * @private
   * @type {any[]}
   * @memberof MobMEditViewPanelCtrlController
   */
  private deResParameters: any[] = [];

  /**
   * @description 当前应用视图参数对象
   * @private
   * @type {any[]}
   * @memberof MobMEditViewPanelCtrlController
   */
  private parameters: any[] = [];

  /**
   * @description 多表单编辑视图面板部件模型数据初始化实例
   * @param {*} [args]
   * @memberof MobMEditViewPanelCtrlController
   */
  public async ctrlModelInit(args?: any) {
    await super.ctrlModelInit(args);
    if (App.isPreviewMode()) {
      return ;
    }    
    this.ctrlService = new AppMobMEditViewPanelService(this.controlInstance);
    await this.ctrlService.loaded();
  }

  /**
   * @description 多表单编辑视图面板部件模型数据加载
   * @memberof MobMEditViewPanelCtrlController
   */
  public async ctrlModelLoad() {
    await super.ctrlModelLoad();
    await this.controlInstance.getEmbeddedPSAppView()?.fill();
    if (this.controlInstance.getEmbeddedPSAppView()?.getPSAppDataEntity()) {
      await this.controlInstance.getEmbeddedPSAppView()?.getPSAppDataEntity()?.fill();
    }
  }

  /**
   * @description 多表单编辑视图面板部件基础数据初始化
   * @memberof MobMEditViewPanelCtrlController
   */
  public ctrlBasicInit() {
    super.ctrlBasicInit();
    this.panelStyle = this.controlInstance.panelStyle ? this.controlInstance.panelStyle : 'ROW';
    if (!App.isPreviewMode()) {
      this.initParameters();
    }
  }

  /**
   * @description 多编辑视图面板初始化
   * @memberof MobMEditViewPanelCtrlController
   */
  public ctrlInit() {
    super.ctrlInit();
    if (this.viewState) {
      this.viewStateEvent = this.viewState.subscribe(({ tag, action, data }: IViewStateParam) => {
        if (!Object.is(this.name, tag)) {
          return;
        }
        if (Object.is(action, 'load')) {
          this.load(data);
        }
      });
    }
  }

  /**
   * @description 初始化嵌入应用视图及实体参数对象
   * @memberof MobMEditViewPanelCtrlController
   */
  public async initParameters() {
    const emView = this.controlInstance.getEmbeddedPSAppView() as IPSAppView;
    const emViewEntity = emView?.getPSAppDataEntity();
    if (emView && emViewEntity) {
      this.deResParameters = Util.formatAppDERSPath(this.context, (emView as IPSAppDEView).getPSAppDERSPaths());
      this.parameters = [
        {
          pathName: Util.srfpluralize(emViewEntity.codeName).toLowerCase(),
          parameterName: emViewEntity.codeName?.toLowerCase(),
          srfmajortext: (ModelTool.getAppEntityMajorField(emViewEntity) as IPSAppDEField).codeName?.toLowerCase(),
        },
      ];
    } else {
      this.deResParameters = [];
      this.parameters = [];
    }
  }

  /**
   * @description 加载数据
   * @param {IParam} [opts] 行为参数
   * @param {IParam} [args] 额外行为参数
   * @param {boolean} [showInfo=true] 是否显示提示信息
   * @param {boolean} [loadding=true] 是否显示loadding效果
   * @return {*}  {Promise<ICtrlActionResult>}
   * @memberof MobMEditViewPanelCtrlController
   */
  public async load(
    opts?: IParam,
    args?: IParam,
    showInfo: boolean = true,
    loadding: boolean = true,
  ): Promise<ICtrlActionResult> {
    if (!this.fetchAction) {
      App.getNoticeService().error('未配置 fetchAction 行为');
      return Promise.resolve({ ret: false, data: null });
    }
    const arg: any = {};
    this.items = [];
    Object.assign(arg, { viewParam: Object.assign(opts, this.viewParam) });
    const tempContext: any = Util.deepCopy(this.context);
    const beforeUIDataParam: IUIDataParam = this.getUIDataParam();
    Object.assign(beforeUIDataParam, { action: this.fetchAction, navContext: tempContext, navParam: arg });
    const beforeLoadResult: any = await this.executeCtrlEventLogic(
      MobMEditViewPanelEvents.BEFORE_LOAD,
      beforeUIDataParam,
    );
    if (beforeLoadResult && beforeLoadResult?.hasOwnProperty('srfret') && !beforeLoadResult.srfret) {
      return Promise.resolve({ ret: false, data: null });
    }
    this.ctrlEvent(MobMEditViewPanelEvents.BEFORE_LOAD, beforeUIDataParam);
    this.onControlRequset('load', tempContext, arg, loadding);
    const response = await this.ctrlService.get(this.fetchAction, tempContext, arg, loadding);
    this.onControlResponse('load', response);
    if (response && response.status === 200) {
      const successUIDataParam: IUIDataParam = this.getUIDataParam();
      Object.assign(successUIDataParam, { action: this.fetchAction, navContext: tempContext, navParam: arg });
      const loadSuccessResult: any = await this.executeCtrlEventLogic(
        MobMEditViewPanelEvents.LOAD_SUCCESS,
        successUIDataParam,
      );
      if (loadSuccessResult && loadSuccessResult?.hasOwnProperty('srfret') && !loadSuccessResult.srfret) {
        return Promise.resolve({ ret: false, data: null });
      }
      this.doItems(response.data);
      this.ctrlEvent(MobMEditViewPanelEvents.LOAD_SUCCESS, successUIDataParam);
      return Promise.resolve({ ret: true, data: response.data });
    } else {
      const errorUIDataParam: IUIDataParam = this.getUIDataParam();
      Object.assign(errorUIDataParam, {
        action: this.fetchAction,
        navContext: tempContext,
        navParam: arg,
        data: [response?.data],
      });
      const loadErrorResult: any = await this.executeCtrlEventLogic(
        MobMEditViewPanelEvents.LOAD_ERROR,
        errorUIDataParam,
      );
      if (loadErrorResult && loadErrorResult?.hasOwnProperty('srfret') && !loadErrorResult.srfret) {
        return Promise.resolve({ ret: false, data: null });
      }
      this.ctrlEvent(MobMEditViewPanelEvents.LOAD_ERROR, errorUIDataParam);
      return Promise.resolve({ ret: false, data: null });
    }
  }

  /**
   * @description 保存数据
   * @param {IParam} [opts] 行为参数
   * @param {IParam} [args] 额外行为参数
   * @param {boolean} [showInfo=true] 是否显示提示信息
   * @param {boolean} [loadding=true] 是否显示loadding效果
   * @memberof MobMEditViewPanelCtrlController
   */
  public save(opts?: IParam, args?: IParam, showInfo: boolean = true, loadding: boolean = true) {
    this.count = 0;
    if (this.items.length > 0) {
      Object.assign(opts, { showInfo: false });
      const embedViewName = this.controlInstance.getEmbeddedPSAppView()?.codeName;
      this.viewState.next({ tag: embedViewName, action: 'save', data: opts });
    } else {
      this.ctrlEvent(MobMEditViewPanelEvents.DATA_SAVE, this.getUIDataParam());
    }
  }

  /**
   * @description 新增数据
   * @param {IParam} [opts] 行为参数
   * @param {IParam} [args] 额外行为参数
   * @param {boolean} [showInfo=true] 是否显示提示信息
   * @param {boolean} [loadding=true] 是否显示loadding效果
   * @return {*}  {Promise<ICtrlActionResult>}
   * @memberof MobMEditViewPanelCtrlController
   */
  public async add(
    opts?: IParam,
    args?: IParam,
    showInfo: boolean = true,
    loadding: boolean = true,
  ): Promise<ICtrlActionResult> {
    if (!this.loaddraftAction) {
      App.getNoticeService().error('未配置 loaddraftAction 行为');
      return Promise.resolve({ ret: false, data: null });
    }
    const arg: any = {};
    Object.assign(arg, opts, { viewparams: this.viewParam });
    const tempContext: any = Util.deepCopy(this.context);
    const beforeUIDataParam: IUIDataParam = this.getUIDataParam();
    Object.assign(beforeUIDataParam, { action: this.loaddraftAction, navContext: tempContext, navParam: arg });
    const beforeLoadResult: any = await this.executeCtrlEventLogic(
      MobMEditViewPanelEvents.BEFORE_ADD,
      beforeUIDataParam,
    );
    if (beforeLoadResult && beforeLoadResult?.hasOwnProperty('srfret') && !beforeLoadResult.srfret) {
      return Promise.resolve({ ret: false, data: null });
    }
    this.ctrlEvent(MobMEditViewPanelEvents.BEFORE_ADD, beforeUIDataParam);
    this.onControlRequset('add', tempContext, arg, loadding);
    const response = await this.ctrlService.loadDraft(this.loaddraftAction, tempContext, arg, this.showBusyIndicator);
    this.onControlResponse('add', response);
    if (response && response.status === 200) {
      const successUIDataParam: IUIDataParam = this.getUIDataParam();
      Object.assign(successUIDataParam, { action: this.loaddraftAction, navContext: tempContext, navParam: arg });
      const addSuccessResult: any = await this.executeCtrlEventLogic(
        MobMEditViewPanelEvents.ADD_SUCCESS,
        successUIDataParam,
      );
      if (addSuccessResult && addSuccessResult?.hasOwnProperty('srfret') && !addSuccessResult.srfret) {
        return Promise.resolve({ ret: false, data: null });
      }
      this.doItems([response.data]);
      this.ctrlEvent(MobMEditViewPanelEvents.ADD_SUCCESS, successUIDataParam);
      if (showInfo) {
        App.getNoticeService().success('添加成功！');
      }
      return Promise.resolve({ ret: true, data: [response.data] });
    } else {
      const errorUIDataParam: IUIDataParam = this.getUIDataParam();
      Object.assign(errorUIDataParam, {
        action: this.loaddraftAction,
        navContext: tempContext,
        navParam: arg,
        data: [response?.data],
      });
      const addErrorResult: any = await this.executeCtrlEventLogic(MobMEditViewPanelEvents.ADD_ERROR, errorUIDataParam);
      if (addErrorResult && addErrorResult?.hasOwnProperty('srfret') && !addErrorResult.srfret) {
        return Promise.resolve({ ret: false, data: null });
      }
      this.ctrlEvent(MobMEditViewPanelEvents.ADD_ERROR, errorUIDataParam);
      if (showInfo) {
        App.getNoticeService().error('添加失败！');
      }
      return Promise.resolve({ ret: false, data: null });
    }
  }

  /**
   * @description 嵌入视图数据改变
   * @param {*} $event 事件参数
   * @return {*}
   * @memberof MobMEditViewPanelCtrlController
   */
  public viewDataChange($event: any) {
    if (!$event) {
      return;
    }
    try {
      $event = JSON.parse($event);
    } catch (error) {
      return;
    }
    if (Object.is($event.action, 'save')) {
      this.count++;
      if (this.items.length === this.count) {
        this.ctrlEvent(MobMEditViewPanelEvents.DATA_SAVE, this.getUIDataParam());
      }
    }
  }

  /**
   * @description 处理数据
   * @private
   * @param {any[]} datas 数据集
   * @memberof MobMEditViewPanelCtrlController
   */
  private doItems(datas: any[]): void {
    const [{ parameterName }] = this.parameters;
    datas.forEach((arg: any) => {
      const id: string = arg[parameterName] ? arg[parameterName] : Util.createUUID();
      const item: any = { id: id, context: {}, viewParam: {} };
      Object.assign(item.context, ViewTool.getIndexViewParam());
      Object.assign(item.context, this.context);
      // 关系应用实体参数
      this.deResParameters.forEach(({ pathName, parameterName }: { pathName: string; parameterName: string }) => {
        if (this.context[parameterName] && !Object.is(this.context[parameterName], '')) {
          Object.assign(item.context, { [parameterName]: this.context[parameterName] });
        } else if (arg[parameterName] && !Object.is(arg[parameterName], '')) {
          Object.assign(item.context, { [parameterName]: arg[parameterName] });
        }
      });
      // 当前视图参数（应用实体视图）
      this.parameters.forEach(
        ({
          pathName,
          parameterName,
          srfmajortext,
        }: {
          pathName: string;
          parameterName: string;
          srfmajortext: string;
        }) => {
          if (arg[parameterName] && !Object.is(arg[parameterName], '')) {
            Object.assign(item.context, { [parameterName]: arg[parameterName] });
          }
          // 当前页面实体主信息
          if (arg[srfmajortext] && !Object.is(arg[srfmajortext], '')) {
            Object.assign(item, { srfmajortext: arg[srfmajortext] });
          }
        },
      );
      //合并视图参数
      Object.assign(item.viewParam, this.viewParam);
      this.items.push(item);
    });
  }
}
